#!/bin/bash
# Copyright (C) 2022 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

set -e

JOBS=6
readonly ALL_LINTERS=clippy

failure() {
    test ${#@} -eq 0 || echo "$(basename "$0"):" "$@" >&2
    exit 1
}

usage() {
    echo "usage: $(basename "$0") [OPTION]..."
    echo "Run the CI pipeline or parts of it."
    echo
    echo "  -b, --build                 build executable"
    echo "  -u, --unit-tests            run unit tests"
    echo "  -F, --check-format          check for correct formatting"
    echo "  -l L,..., --lint=L,...      run linters, 'all' means '${ALL_LINTERS}'"
    echo "  -a, --all                   shortcut for -b -u -F -l all"
    echo "  -f, --format                format sources"
    echo "  -D, --documentation         generate documentation"
    echo "  -j N, --jobs=N              allow N jobs at once, default is ${JOBS}"
    echo "  -h, --help                  show this help"
}

parse_options() {
    # Yes, all those option variables are global.
    RUN_BUILD=no
    RUN_UNIT_TESTS=no
    RUN_CHECK_FORMAT=no
    RUN_CLIPPY=no
    RUN_FORMAT=no
    RUN_DOCUMENTATION=no

    if ! OPTIONS=$(getopt --options 'buFl:afDj:h' --long 'build,unit-tests,check-format,lint:,all,format,documentation,jobs:,help' --name "$(basename "$0")" -- "$@"); then
        usage >&2
        failure
    fi
    eval set -- "$OPTIONS"
    unset OPTIONS

    while true; do
        case "$1" in
            '-b' | '--build')
                RUN_BUILD=yes
                shift
                ;;
            '-u' | '--unit-tests')
                RUN_UNIT_TESTS=yes
                shift
                ;;
            '-F' | '--check-format')
                RUN_CHECK_FORMAT=yes
                shift
                ;;
            '-l' | '--lint')
                test "$2" = "all" && LINTERS="${ALL_LINTERS}" || LINTERS="$2"
                for LINTER in ${LINTERS//,/ }; do
                    case ,"${ALL_LINTERS}", in
                        *,"${LINTER}",*)
                            FLAG="RUN_${LINTER//-/_}"
                            eval "${FLAG^^}=yes"
                            ;;
                        *) failure "unknown linter: ${LINTER}" ;;
                    esac
                done
                shift 2
                ;;
            '-a' | '--all')
                RUN_BUILD=yes
                RUN_UNIT_TESTS=yes
                RUN_CHECK_FORMAT=yes
                RUN_CLIPPY=yes
                shift
                ;;
            '-f' | '--format')
                RUN_FORMAT=yes
                shift
                ;;
            '-D' | '--documentation')
                RUN_DOCUMENTATION=yes
                shift
                ;;
            '-j' | '--jobs')
                JOBS="$2"
                shift 2
                ;;
            '-h' | '--help')
                usage
                exit 0
                ;;
            '--')
                shift
                test ${#@} -eq 0 || failure "extra arguments:" "$@"
                break
                ;;
            *) failure "internal error" ;;
        esac
    done

    readonly RUN_BUILD RUN_UNIT_TESTS RUN_CHECK_FORMAT RUN_CLIPPY RUN_FORMAT RUN_DOCUMENTATION JOBS
}

run_format() {
    bazel run //:format "$PWD"
}

run_check_format() {
    bazel run //:format.check "$PWD"
}

main() {
    # Change to the directory where this script resides, it makes many things easier
    # and we can call this script from everywhere.
    cd -- "${BASH_SOURCE%/*}"
    parse_options "$@"
    # TODO: Re-evaluate usage of --all-targets below
    test ${RUN_BUILD} = yes && bazel build :all
    test ${RUN_UNIT_TESTS} = yes && bazel test :all
    test ${RUN_CHECK_FORMAT} = yes && run_check_format
    test ${RUN_CLIPPY} = yes && bazel build --config=clippy :all
    test ${RUN_FORMAT} = yes && run_format
    test ${RUN_DOCUMENTATION} = yes && bazel build :doc
    true
}

main "$@"
